package statistics

import (
	"context"
	"encoding/json"
	"fmt"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/models"
	"sort"
	"strings"

	"github.com/golang-module/carbon/v2"
	"github.com/samber/lo"
	"gorm.io/gorm"
)

type GoodsStatisticService struct{}

type GoodsDescReturn struct {
	GoodsName           string  `json:"goods_name"`
	ClickNum            int     `json:"click_num"`
	Count               int     `json:"count"`
	MyNotPayOrderCount  int     `json:"my_not_pay_order_count"`
	MyPaymentAmount     float64 `json:"my_payment_amount"`
	MyRefundOrderAmount float64 `json:"my_refund_order_amount"`
	MyRefundOrderCount  int     `json:"my_refund_order_count"`
	MyStartOrderCount   int     `json:"my_start_order_count"`
	MySuccessOrderCount int     `json:"my_success_order_count"`
	OrderPercent        string  `json:"order_percent"`
	GMV                 float64 `json:"gmv"`
}

func (gss GoodsStatisticService) GoodsDesc(ctx context.Context, db *gorm.DB, merchantID, salesID, startTime, endTime, goodsName string,
	goodsType, dataType int, areas1, areas2, areas3, areas5 string, shopIDList []string) (data []GoodsDescReturn, err error) {
	tx := db.Model(&models.MaOrder{})
	if endTime != "" {
		endTime = endTime + " 23:59:59"
	}
	var startTimeUnix, endTimeUnix int64
	if startTime != "" && endTime != "" {
		tx.Where("add_time between ? and ?", startTime, endTime)
		startTimeUnix = carbon.Parse(startTime).Timestamp()
		endTimeUnix = carbon.Parse(endTime).Timestamp()
	}
	if goodsName != "" {
		unicodeName, _ := common.UnicodeEncode(goodsName)
		tx.Where("count_data like '%" + strings.ReplaceAll(unicodeName, "\\", "_") + "%'")
	}
	merchantIDs, err1 := common.Order{}.GetMerchantChildren(ctx, merchantID, shopIDList)
	if err1 != nil {
		err = err1
		return
	}
	tx.Where("merchant_id in ?", merchantIDs)
	if salesID != "" {
		tx.Where("sales_id in (?)", strings.Split(salesID, ","))
	}
	if areas1 != "" {
		tx.Where("areas1 in (?)", strings.Split(areas1, ","))
	}
	if areas2 != "" {
		tx.Where("areas2 in (?)", strings.Split(areas2, ","))
	}
	if areas3 != "" {
		tx.Where("areas3 in (?)", strings.Split(areas3, ","))
	}
	// if areas5 != "" {
	// 	tx.Where("areas5 in (?)", strings.Split(areas5, ","))
	// }
	var OrderGoodsList []struct {
		GoodsName   string  `json:"goods_name"`
		GoodsID     string  `json:"goods_id"`
		Count       int     `json:"count"`
		OrderStatus int     `json:"order_status"`
		SalesID     string  `json:"sales_id"`
		TotalMoney  float64 `json:"total_money"`
	}
	field := "json_extract_c(count_data, '$.GoodsName') AS goods_name," +
		"json_extract_c(count_data, '$.GoodsID') AS goods_id," +
		"COUNT(order_id) AS count," +
		"order_status, sales_id," +
		"sum(payment_amount) as total_money"
	tx.Group("goods_id, order_status, sales_id").
		Order("goods_id").
		Select(field).
		Find(&OrderGoodsList)

	// 商品id => []订单数组
	var goodsIDOrderMap = make(map[string][]struct {
		GoodsName   string  `json:"goods_name"`
		GoodsID     string  `json:"goods_id"`
		Count       int     `json:"count"`
		OrderStatus int     `json:"order_status"`
		SalesID     string  `json:"sales_id"`
		TotalMoney  float64 `json:"total_money"`
	})
	var GoodsNameIDMap = make(map[string][]string) //商品名称  => []商品id数组
	var salesIDs []string
	for _, v := range OrderGoodsList {
		json.Unmarshal([]byte("\""+v.GoodsName+"\""), &v.GoodsName)
		goodsIDOrderMap[v.GoodsID] = append(goodsIDOrderMap[v.GoodsID], v)
		if !lo.Contains(GoodsNameIDMap[v.GoodsName], v.GoodsID) {
			GoodsNameIDMap[v.GoodsName] = append(GoodsNameIDMap[v.GoodsName], v.GoodsID)
		}
		if !lo.Contains(salesIDs, v.SalesID) {
			salesIDs = append(salesIDs, v.SalesID)
		}
	}
	// 商品点击量
	var GoodsClickList []struct {
		GoodsID  string `json:"goods_id"`
		ClickNum int    `json:"click_num"`
	}
	tx2 := db.Model(&models.MaGoodsClick{})
	if len(salesIDs) > 0 {
		tx2.Where("sales_id in ?", salesIDs)
	}
	if startTime != "" && endTime != "" {
		tx2.Where("new_start_time between ? and ?", startTimeUnix, endTimeUnix)
	}
	tx2.Order("goods_id asc").
		Select("goods_id, click_num").
		Find(&GoodsClickList)
	// 商品ID -> 点击量
	var GoodsClickMap = make(map[string]int)
	for _, v := range GoodsClickList {
		GoodsClickMap[v.GoodsID] += v.ClickNum
	}

	var Result = []GoodsDescReturn{}
	for goodsName, goodsIDList := range GoodsNameIDMap { // 商品名称 商品id数组
		var item GoodsDescReturn
		item.GoodsName = goodsName
		for _, goodsID := range goodsIDList { // 商品id
			for _, v := range goodsIDOrderMap[goodsID] { // 商品id = > 订单列表
				item.Count += v.Count
				item.GMV += v.TotalMoney
				if v.OrderStatus == 3 || v.OrderStatus == 4 || v.OrderStatus == 6 {
					item.MyStartOrderCount += v.Count
				}
				if v.OrderStatus == 3 {
					item.MyNotPayOrderCount += v.Count
				}
				if v.OrderStatus == 4 {
					item.MyPaymentAmount += v.TotalMoney
					item.MySuccessOrderCount += v.Count
				}
				if v.OrderStatus == 6 {
					item.MyRefundOrderAmount += v.TotalMoney
					item.MyRefundOrderCount += v.Count
				}
			}
			if _, ok := GoodsClickMap[goodsID]; ok {
				item.ClickNum += GoodsClickMap[goodsID]
			}
		}
		if item.MyStartOrderCount == 0 {
			item.OrderPercent = "0%"
		} else {
			percent := common.Decimal(float64(item.MySuccessOrderCount)/float64(item.MyStartOrderCount), 4) * 100
			item.OrderPercent = fmt.Sprintf("%.2f", percent) + "%"
		}
		Result = append(Result, item)
	}
	sort.Slice(Result, func(i, j int) bool {
		return Result[i].MyPaymentAmount > Result[j].MyPaymentAmount
	})
	return Result, nil
}
